function critter(x, y, code)
 {
    //coords, direction, speed and color
    this.x = x || 0;
    this.y = y || 0;
    this.r = Math.PI*(1 - 2*Math.random());
    this.dr = 0;
    this.v = 0;
    this.eat = 0;
    this.mate = 0;
    this.kill = 0;
    this.partener = null;
    this.hasPartener = false;
    
    this.energy = maxEnergyValue;
    this.size = 15;
    this.brain = new brain();
    this.brain.params = null;
    ////construct brain
    this.brain.buildFF(3,8,8,4);
    if (code)
        this.brain.fromCode(code);
    this.hue = 0;
    var c = this.brain.toCode();
    for (var iter = 0; iter < c.length; iter++)
    {
        this.hue += c[iter];
    }
    this.hue = (this.hue + 5) * 25.5;
    this.fitness = 0;
 }
 
 critter.prototype.update = function()
 {
    with(this)
    {
        v *= 0.8;
        dr *= 0.8;
        if (brain.neurons[brain.motorIndexes[0]].spike)
        {
            v += 0.5;
        }

        if (brain.neurons[brain.motorIndexes[1]].spike)
        {
            dr -= 0.1;
        }
        if (brain.neurons[brain.motorIndexes[2]].spike)
        {
            dr += 0.1;
        }
        v = Math.min(v, 10);
        r += dr;
        kill += brain.neurons[brain.motorIndexes[3]].spike;
        kill *= 0.5;

        eat = 1;//brain.neurons[brain.motorIndexes[5]].spike;
        mate = 1;//brain.neurons[brain.motorIndexes[4]].spike;
        
        energy *= metabolism;
        energy -= Math.abs(v)/2;
        energy -= Math.abs(dr);
        //energy -= Math.abs(brain.neurons[brain.motorIndexes[0]].value);
        brain.run();
    }
 }
 
 critter.prototype.move = function()
 {
    with(this)
    {
        x += 10 * v * Math.cos(r);
        y += 10 * v * Math.sin(r);

        //fit to screen
        fit(this, fitMode);
    }
 }
 
 critter.prototype.interact = function(crop, critters)
 {
    var dist = Number.POSITIVE_INFINITY;
    var index = 0;
    var dx,dy,d;
    
    
    //eat
    var fx,fy;
    for (var i = 0; i < crop.length; i++)
    {
        dx = this.x - crop[i].x;
        dy = this.y - crop[i].y;
        d = dx*dx + dy*dy;
        if (d < dist)
        {
            dist = d;
            index = i;
        }
    }
    fx = dx;
    fy = dy;
    if (dist < this.size*this.size /*&& this.eat > 0*/)
    {
        this.fitness+=10;
        if (maxEnergyValue - this.energy > crop[index].energy)
        {
            this.energy += crop[index].energy;
            crop.remove(index);
        }
        else
        {
            crop[index].energy -= maxEnergyValue - this.energy;
            this.energy = maxEnergyValue;
        }
    }
    
    //try to mate or kill
    dist = Number.POSITIVE_INFINITY;
    index = 0;
    var h = 0;
    var cx,cy;
    if (!this.hasPartener)
    {
        for (var i = 0; i < critters.length; i++)
        {
            if (this != critters[i])
            {
                dx = this.x - critters[i].x;
                dy = this.y - critters[i].y;
                d = dx*dx + dy*dy;
                if (d < dist)
                {
                    dist = d;
                    index = i;
                }
            }
        }
        this.partener = critters[index];
        critters[index].partener = this;
        this.hasPartener = true;
        critters[index].hasPartener = true;
    }
    
    cx = this.x - this.partener.x;;
    cy = this.y - this.partener.y;
    dist = cx*cx + cy*cy;
    h = this.partener.kill;
    
    if (dist < this.size*this.partener.size)
    {
        if (critters.length < maxCritter && this.mate > 0 && this.energy > maxEnergyValue / 4)
        {
            var jay = new critter(this.x, this.y, crossover(this.brain.toCode(),this.partener.brain.toCode()));
            jay.energy = this.energy/2;
            this.energy *= 0.5;
            if (this.partener.mate > 0 && this.partener.energy > maxEnergyValue / 2);
            {
                jay.energy += this.partener.energy / 2;
                this.partener.energy *= 0.5;
            }
            this.fitness++;
            critters.push(jay);
        }
        
        if (this.kill > 0.5 && this.kill > this.partener.kill)
        {
            this.energy *= 0.6;
            
            if (crop.length < maxCrop)
            {
                var snack = new food(this.partener.x, this.partener.y, crop);
                snack.energy += this.partener.energy;
                snack.hue = 0;
                crop.push(snack);
            }
            else
            {
                this.energy = Math.min(this.energy + this.partener.energy, maxEnergyValue);
            }
            //destroy the mofo
            for (var i=0; i < critters.length; i++)
            { 
                if (critters[i] == this.partener)
                {
                    critters.splice(i,1);
                    break;
                }
            }
        }
        this.hasPartener = false;
    }
    
    
    //divide
	if (critters.length < maxCritter && this.mate > 0 && this.energy > maxEnergyValue * 3 / 4)
	{
	    var jay = new critter(this.x, this.y, mutate(this.brain.toCode()));
	    jay.energy = this.energy/2;
	    this.energy *= 0.5;
	    this.fitness++;
	    critters.push(jay);
	}
		
	//update brain inputs
    var crop_angle = this.r-Math.atan2(cy,cx);
    var crit_angle = this.r-Math.atan2(fy,fx);
    this.brain.params = [1/crop_angle, 1/crit_angle, Math.sqrt(this.energy)];
 }
 
 critter.prototype.draw = function(context, viewport)
 {
    with(this)
    {
        if (x > viewport.left && x < viewport.right && y > viewport.top && y < viewport.bottom)
        {
            var pp = (mate + 1) * size;
            var oo = (kill + 1) * size;
            context.save();
                context.translate(x - viewport.left, y - viewport.top);
                context.rotate(r);
                context.beginPath();
                context.lineWidth = 2;
                context.moveTo(oo,0);
                context.lineTo(0,pp/3);
                context.lineTo(0,-pp/3);
                context.closePath();
                context.strokeStyle = 'hsl(' + hue + ', ' + energy.toFixed(2) + '%, 50%)';
                //context.shadowBlur = 50;
                context.stroke();
            context.restore();
        }
    }
 }